﻿// Decompiled with JetBrains decompiler
// Type: Commom.Util.Reflection
// Assembly: MT5Trade, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 8045A2CB-DBD6-41AD-8804-F98CAC1BDC8D
// Assembly location: C:\projects\trade\trade_tool\trade0812\MT5Trade.dll

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;

#nullable enable
namespace Commom.Util;

public static class Reflection
{
  public static string GetDescription<T>()
  {
    return Commom.Util.Reflection.GetDescription((MemberInfo) Common.GetType<T>());
  }

  public static string GetDescription<T>(string memberName)
  {
    return Commom.Util.Reflection.GetDescription(Common.GetType<T>(), memberName);
  }

  public static string GetDescription(Type type, string memberName)
  {
    return type == (Type) null || string.IsNullOrWhiteSpace(memberName) ? string.Empty : Commom.Util.Reflection.GetDescription(((IEnumerable<MemberInfo>) type.GetTypeInfo().GetMember(memberName)).FirstOrDefault<MemberInfo>());
  }

  public static string GetDescription(MemberInfo member)
  {
    if (member == (MemberInfo) null)
      return string.Empty;
    DescriptionAttribute customAttribute = member.GetCustomAttribute<DescriptionAttribute>();
    return customAttribute == null ? member.Name : customAttribute.Description;
  }

  public static List<Type> FindTypes<TFind>(params Assembly[] assemblies)
  {
    return Commom.Util.Reflection.FindTypes(typeof (TFind), assemblies);
  }

  public static List<Type> FindTypes(Type findType, params Assembly[] assemblies)
  {
    List<Type> source = new List<Type>();
    foreach (Assembly assembly in assemblies)
      source.AddRange((IEnumerable<Type>) Commom.Util.Reflection.GetTypes(findType, assembly));
    return source.Distinct<Type>().ToList<Type>();
  }

  private static List<Type> GetTypes(Type findType, Assembly assembly)
  {
    List<Type> result = new List<Type>();
    if (assembly == (Assembly) null)
      return result;
    Type[] types;
    try
    {
      types = assembly.GetTypes();
    }
    catch (ReflectionTypeLoadException)
    {
      return result;
    }
    foreach (Type type in types)
      Commom.Util.Reflection.AddType(result, findType, type);
    return result;
  }

  private static void AddType(List<Type> result, Type findType, Type type)
  {
    if (type.IsInterface || type.IsAbstract || !findType.IsAssignableFrom(type) && !Commom.Util.Reflection.MatchGeneric(findType, type))
      return;
    result.Add(type);
  }

  private static bool MatchGeneric(Type findType, Type type)
  {
    if (!findType.IsGenericTypeDefinition)
      return false;
    Type genericTypeDefinition = findType.GetGenericTypeDefinition();
    foreach (Type type1 in type.FindInterfaces((TypeFilter) ((filter, criteria) => true), (object) null))
    {
      if (type1.IsGenericType)
        return genericTypeDefinition.IsAssignableFrom(type1.GetGenericTypeDefinition());
    }
    return false;
  }

  public static List<TInterface> GetInstancesByInterface<TInterface>(params Assembly[] assemblies)
  {
    return Commom.Util.Reflection.FindTypes<TInterface>(assemblies).Select<Type, TInterface>((Func<Type, TInterface>) (t => Commom.Util.Reflection.CreateInstance<TInterface>(t))).ToList<TInterface>();
  }

  public static T CreateInstance<T>(Type type, params object[] parameters)
  {
    return ConvertUtil.To<T>(Activator.CreateInstance(type, parameters));
  }

  public static Assembly GetAssembly(string assemblyName)
  {
    return Assembly.Load(new AssemblyName(assemblyName));
  }

  public static bool IsBool(MemberInfo member)
  {
    if (member == (MemberInfo) null)
      return false;
    switch (member.MemberType)
    {
      case MemberTypes.Property:
        return Commom.Util.Reflection.IsBool((PropertyInfo) member);
      case MemberTypes.TypeInfo:
        return member.ToString() == "System.Boolean";
      default:
        return false;
    }
  }

  private static bool IsBool(PropertyInfo property)
  {
    return property.PropertyType == typeof (bool) || property.PropertyType == typeof (bool?);
  }

  public static bool IsEnum(MemberInfo member)
  {
    if (member == (MemberInfo) null)
      return false;
    switch (member.MemberType)
    {
      case MemberTypes.Property:
        return Commom.Util.Reflection.IsEnum((PropertyInfo) member);
      case MemberTypes.TypeInfo:
        return ((Type) member).IsEnum;
      default:
        return false;
    }
  }

  private static bool IsEnum(PropertyInfo property)
  {
    if (property.PropertyType.GetTypeInfo().IsEnum)
      return true;
    Type underlyingType = Nullable.GetUnderlyingType(property.PropertyType);
    return !(underlyingType == (Type) null) && underlyingType.GetTypeInfo().IsEnum;
  }

  public static bool IsDate(MemberInfo member)
  {
    if (member == (MemberInfo) null)
      return false;
    switch (member.MemberType)
    {
      case MemberTypes.Property:
        return Commom.Util.Reflection.IsDate((PropertyInfo) member);
      case MemberTypes.TypeInfo:
        return member.ToString() == "System.DateTime";
      default:
        return false;
    }
  }

  private static bool IsDate(PropertyInfo property)
  {
    return property.PropertyType == typeof (DateTime) || property.PropertyType == typeof (DateTime?);
  }

  public static bool IsInt(MemberInfo member)
  {
    if (member == (MemberInfo) null)
      return false;
    switch (member.MemberType)
    {
      case MemberTypes.Property:
        return Commom.Util.Reflection.IsInt((PropertyInfo) member);
      case MemberTypes.TypeInfo:
        return member.ToString() == "System.Int32" || member.ToString() == "System.Int16" || member.ToString() == "System.Int64";
      default:
        return false;
    }
  }

  private static bool IsInt(PropertyInfo property)
  {
    return property.PropertyType == typeof (int) || property.PropertyType == typeof (int?) || property.PropertyType == typeof (short) || property.PropertyType == typeof (short?) || property.PropertyType == typeof (long) || property.PropertyType == typeof (long?);
  }

  public static bool IsNumber(MemberInfo member)
  {
    if (member == (MemberInfo) null)
      return false;
    if (Commom.Util.Reflection.IsInt(member))
      return true;
    switch (member.MemberType)
    {
      case MemberTypes.Property:
        return Commom.Util.Reflection.IsNumber((PropertyInfo) member);
      case MemberTypes.TypeInfo:
        return member.ToString() == "System.Double" || member.ToString() == "System.Decimal" || member.ToString() == "System.Single";
      default:
        return false;
    }
  }

  private static bool IsNumber(PropertyInfo property)
  {
    return property.PropertyType == typeof (double) || property.PropertyType == typeof (double?) || property.PropertyType == typeof (Decimal) || property.PropertyType == typeof (Decimal?) || property.PropertyType == typeof (float) || property.PropertyType == typeof (float?);
  }

  public static bool IsCollection(Type type)
  {
    return type.IsArray || Commom.Util.Reflection.IsGenericCollection(type);
  }

  public static bool IsGenericCollection(Type type)
  {
    if (!type.IsGenericType)
      return false;
    Type genericTypeDefinition = type.GetGenericTypeDefinition();
    return genericTypeDefinition == typeof (IEnumerable<>) || genericTypeDefinition == typeof (IReadOnlyCollection<>) || genericTypeDefinition == typeof (IReadOnlyList<>) || genericTypeDefinition == typeof (ICollection<>) || genericTypeDefinition == typeof (IList<>) || genericTypeDefinition == typeof (List<>);
  }

  public static List<Assembly> GetAssemblies(string directoryPath)
  {
    return ((IEnumerable<string>) Directory.GetFiles(directoryPath, "*.*", SearchOption.AllDirectories)).ToList<string>().Where<string>((Func<string, bool>) (t => t.EndsWith(".exe") || t.EndsWith(".dll"))).Select<string, Assembly>((Func<string, Assembly>) (path => Assembly.Load(new AssemblyName(path)))).ToList<Assembly>();
  }

  public static List<Item> GetPublicProperties(object instance)
  {
    return ((IEnumerable<PropertyInfo>) instance.GetType().GetProperties()).ToList<PropertyInfo>().Select<PropertyInfo, Item>((Func<PropertyInfo, Item>) (t => new Item(t.Name, t.GetValue(instance)))).ToList<Item>();
  }

  public static Type GetTopBaseType<T>() => Commom.Util.Reflection.GetTopBaseType(typeof (T));

  public static Type GetTopBaseType(Type type)
  {
    if (type == (Type) null)
      return (Type) null;
    return type.IsInterface || type.BaseType == typeof (object) ? type : Commom.Util.Reflection.GetTopBaseType(type.BaseType);
  }

  public static Type GetElementType(Type type)
  {
    if (!Commom.Util.Reflection.IsCollection(type))
      return type;
    if (type.IsArray)
      return type.GetElementType();
    Type[] genericArguments = type.GetTypeInfo().GetGenericArguments();
    return genericArguments != null && genericArguments.Length != 0 ? genericArguments[0] : throw new ArgumentException("泛型类型参数不能为空");
  }
}
